function player( init_method, frame_method, param )
% payer( init_method, frame_method) - general purpose player. Initializes
% with init_method( param ), plays each frame with frame_methd(param). Use global vars:
% player_frames - numeber of frame, must be set by init_method
% player_current_frame - current frame number, 1-player_frames
% player_image  - image to paint on

% AUTOSTOP

% globals
global player_frames ;
global player_current_frame ;
global player_playing;
global player_timer

global player_frame_method
global player_param  
global player_cache player_cached_frames player_caching
global player_image

% init
player_frame_method = frame_method;
player_param = param;
player_playing = 1;
player_current_frame = 1;
player_caching = 1;

% clear cache
player_cache = [];
player_cached_frames = 0;


% current figure handle
f = gcf;
w= 640;
h=480;


% setup figure -  double buffering and other stuff
set( f, 'DoubleBuffer', 'on' );
set( f, 'DeleteFcn', @on_close );
set( f, 'Position', [ 10 10 w+20 h+60 ] );

% setup axis
a = axes('Units', 'pixels', 'Position', [10 40 w h] , 'DataAspectRatio', [1 1 1], 'YDir', 'reverse', 'XLim', [0 w], 'YLim', [0 h]...
	, 'XLimMode', 'manual', 'YLimMode', 'manual' );
hold on;

% cretae buttons
hpause = uicontrol( f, ...
	'Style', 'pushbutton', ...
	'Position', [10 10 100 20 ], ...
	'String', 'play/pause', ...
	'Callback', @on_pause );

% stop
hstop = uicontrol( f, ...
	'Style', 'pushbutton', ...
	'Position', [120 10 100 20 ], ...
	'String', 'stop', ...
	'Callback', @on_stop );

% prev
hstop = uicontrol( f, ...
	'Style', 'pushbutton', ...
	'Position', [240 10 20 20 ], ...
	'String', '<', ...
	'Callback', @on_prev );

% next
hstop = uicontrol( f, ...
	'Style', 'pushbutton', ...
	'Position', [260 10 20 20 ], ...
	'String', '>', ...
	'Callback', @on_next );

% image
player_image = image;

% init
feval( init_method, param );

% create timer
player_timer = timer('TimerFcn', @on_timer, 'Period', 0.05, 'ExecutionMode', 'fixedRate', 'BusyMode', 'queue' );

% TODO o test - version w/o timer
start( player_timer );
display_frame;
% for i = 1:player_frames
% 	display_frame;
% 	player_current_frame = player_current_frame + 1;
% 	pause( 0.05 );
% end


return;

% ------------------ pause handler --------------
function on_pause( o, e )

global player_playing;

player_playing = ~player_playing;

% ----------------- stop handler -----------------
function on_stop( o, e )

global player_frames player_current_frame player_playing;

player_playing = 0;
player_current_frame=1;
display_frame;

% ------------------- next handler ------------------
function on_next( o, e )

global player_frames player_current_frame player_playing;

player_playing = 0;
if player_current_frame < player_frames
	player_current_frame = player_current_frame + 1;
	display_frame;
end

% ------------------- next handler ------------------
function on_prev( o, e )

global player_frames player_current_frame player_playing;

player_playing = 0;
if player_current_frame > 1
	player_current_frame = player_current_frame - 1;
	display_frame;
end


% ------------------- timer handler -------------
function on_timer( o, e)

global player_frames player_current_frame player_playing;

if player_current_frame <= player_frames
	if player_playing ~= 0
		display_frame;
		player_current_frame = player_current_frame + 1;
	end
end



% ----------------------- display frame --------------
function display_frame()

global player_caching player_frame_method player_param;

if player_caching ~= 0
	global player_movie player_current_frame player_cache player_cached_frames;
	if player_current_frame > player_cached_frames
		% render frame using supplied renderering function
		feval( player_frame_method, player_param );
		% cache the frame 
		player_cached_frames = player_current_frame;
		f = getframe;
		player_cache =  [player_cache f];
	else
		global player_image;
		frame = player_cache( player_current_frame );
		set( player_image, 'CData', frame.cdata );
	end
else
	% no csching, render frame using supplied renderering function
	feval( player_frame_method, player_param );
end


% ------------------------ close handler ----------------------
function on_close( o, e )
global player_timer

disp('end - deleting timer');
stop( player_timer );
delete( player_timer );

hold off;
